//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2006
// (c) trueblacker@mail.ru, tiled export code contribution, 2006
//
// OziExplorer .map export wizard.
//

# include "StdAfx.h"
# include "Resource.h"
# include "OziMapWizard.h"
# include "Map.h"
# include "Position.h"
# include "Scale.h"
# include "EditRect.h"
# include "ParseHelpers.h"
# include "PrintUnits.h"
# include "PropertyPages.h"
# include "File.h"
# include "Static.h"
# include "Globals.h"

static bool g_bCanceled = false;

static
void FillRect (HWND _hWnd, const rect_t & _rect) {
	char buf [32];

	PrintLon (buf, _rect.x0);
	::SetDlgItemText (_hWnd, IDC_LEFT, buf);
	PrintLon (buf, _rect.x1);
	::SetDlgItemText (_hWnd, IDC_RIGHT, buf);
	PrintLat (buf, _rect.y0);
	::SetDlgItemText (_hWnd, IDC_BOTTOM, buf);
	PrintLat (buf, _rect.y1);
	::SetDlgItemText (_hWnd, IDC_TOP, buf);

	// Estimate bitmap size.
	int X0, X1, Y0, Y1;
	{
		CCritSec::CLock lock (g_cs);

		rect_t rect;
		rect_t::Intersection (rect, g_map.rectBound, _rect);

		X0 = XToScreen (rect.x0);
		X1 = XToScreen (rect.x1);
		Y0 = YToScreen (rect.y0);
		Y1 = YToScreen (rect.y1);
	}
	const size_t cWidth  = X1 - X0;
	const size_t cHeight = Y0 - Y1;
	::sprintf (buf, "%0.1f MB", float (cWidth)*cHeight*3/(1024*1024));
	::SetDlgItemText (_hWnd, IDC_BITMAP_SIZE, buf);
}

INT_PTR CALLBACK COziMapWizard::_PageProc (HWND _hWnd, UINT _uMsg, WPARAM _wParam, LPARAM _lParam) {
	COziMapWizard * const pThis = reinterpret_cast<COziMapWizard *> (::GetWindowLong (_hWnd, GWL_USERDATA));

	switch (_uMsg) {
		case WM_INITDIALOG: {
			CenterPropertyPages (_hWnd);

			//
			// Prepare access to wizard's data.
			//

			const PROPSHEETPAGE * const pPage = reinterpret_cast<PROPSHEETPAGE *> (_lParam);
			COziMapWizard * const pThis = reinterpret_cast<COziMapWizard *> (pPage->lParam);
			::SetWindowLong (_hWnd, GWL_USERDATA, pPage->lParam);

			assert (pThis);

			//
			// Prepare fields.
			//

			// Prepare bitmap.
			SetStaticPicture (_hWnd, IDC_BITMAP, IDR_ShpWizard);

			// .map name.
			char strFileName [MAX_PATH + 1];
			::strncpy (strFileName, g_strFileName, MAX_PATH);
			char * strExt = ::strrchr (strFileName, '.');
			if (strExt != NULL)
				* strExt = '\0';
			else
				strExt = strFileName + ::strlen (strFileName);
			::strcpy (strExt, ".map");

			::SetDlgItemText (_hWnd, IDC_MAP_FILE, strFileName);
			::SendDlgItemMessage (_hWnd, IDC_MAP_FILE, EM_LIMITTEXT, MAX_PATH, 0);
			pThis->m_strMapFileName = strFileName;

			// .bmp name
			::strcpy (strExt, ".bmp");
			::SetDlgItemText (_hWnd, IDC_BMP_FILE, strFileName);
			::SendDlgItemMessage (_hWnd, IDC_BMP_FILE, EM_LIMITTEXT, MAX_PATH, 0);
			pThis->m_strBmpFileName = strFileName;

			// Rectangle.
			{
				CCritSec::CLock lock (g_cs);
				GetVisibleRect (pThis->m_rect);
			}
			FillRect (_hWnd, pThis->m_rect);

			// Scale.
			char strScale [64];
			GetScale (g_fScale, strScale);
			::SetDlgItemText (_hWnd, IDC_SCALE, strScale);

			// Tiled.
			::CheckDlgButton (_hWnd, IDC_TILE, pThis->m_bIsTiled ? BST_CHECKED : BST_UNCHECKED);

			// Columns.
            ::EnableWindow (::GetDlgItem (_hWnd, IDC_COLS), pThis->m_bIsTiled ? TRUE : FALSE);
            ::SetDlgItemInt (_hWnd, IDC_COLS, pThis->m_cRows, FALSE);

			// Rows.
            ::EnableWindow (::GetDlgItem (_hWnd, IDC_ROWS), pThis->m_bIsTiled ? TRUE : FALSE);
            ::SetDlgItemInt (_hWnd, IDC_ROWS, pThis->m_cCols, FALSE);

			return FALSE;
		}

		case WM_COMMAND:
			switch (LOWORD (_wParam)) {
				case IDC_MAP_FILE: {
					if (HIWORD (_wParam) == EN_UPDATE) {
						char strFileName [MAX_PATH + 1];
						::GetDlgItemText (_hWnd, IDC_MAP_FILE, strFileName, MAX_PATH);

						pThis->m_strMapFileName = strFileName;

						// Update .bmp
						char * strExt = ::strrchr (strFileName, '.');
						if (strExt != NULL)
							* strExt = '\0';
						else
							strExt = strFileName + ::strlen (strFileName);
						::strcpy (strExt, ".bmp");

						::SetDlgItemText (_hWnd, IDC_BMP_FILE, strFileName);
						pThis->m_strBmpFileName = strFileName;
					}
					break;
				}

				case IDC_MAP_FILE_SELECT: {
					char strFileName [MAX_PATH + 1];
					::GetDlgItemText (_hWnd, IDC_MAP_FILE, strFileName, MAX_PATH);

					OPENFILENAME ofn;
					::ZeroMemory (& ofn, sizeof (OPENFILENAME));
					ofn.lStructSize = sizeof (OPENFILENAME);
					ofn.hwndOwner = g_hWnd;
					ofn.hInstance = g_hResInst;
					ofn.lpstrFile = strFileName;
					ofn.nMaxFile = sizeof (strFileName);
					ofn.lpstrDefExt = "map";
					ofn.nFilterIndex = 1;
					ofn.lpstrFilter = "OziExplorer map (*.map)\0*.map\0";
					ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_ENABLESIZING | OFN_NOREADONLYRETURN | OFN_OVERWRITEPROMPT;
					if (::GetSaveFileName (& ofn) == FALSE)
						break;

					::SetDlgItemText (_hWnd, IDC_MAP_FILE, strFileName);
					pThis->m_strMapFileName = strFileName;

					// Update .bmp
					char * strExt = ::strrchr (strFileName, '.');
					if (strExt != NULL)
						* strExt = '\0';
					else
						strExt = strFileName + ::strlen (strFileName);
					::strcpy (strExt, ".bmp");

					::SetDlgItemText (_hWnd, IDC_BMP_FILE, strFileName);
					pThis->m_strBmpFileName = strFileName;

					break;
				}

				case IDC_BMP_FILE_SELECT: {
					char strFileName [MAX_PATH + 1];
					::GetDlgItemText (_hWnd, IDC_BMP_FILE, strFileName, MAX_PATH);

					OPENFILENAME ofn;
					::ZeroMemory (& ofn, sizeof (OPENFILENAME));
					ofn.lStructSize = sizeof (OPENFILENAME);
					ofn.hwndOwner = g_hWnd;
					ofn.hInstance = g_hResInst;
					ofn.lpstrFile = strFileName;
					ofn.nMaxFile = sizeof (strFileName);
					ofn.lpstrDefExt = "map";
					ofn.nFilterIndex = 1;
					ofn.lpstrFilter = "Windows bitmap (*.bmp)\0*.bmp\0";
					ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_ENABLESIZING | OFN_NOREADONLYRETURN | OFN_OVERWRITEPROMPT;
					if (::GetSaveFileName (& ofn) == FALSE)
						break;

					::SetDlgItemText (_hWnd, IDC_BMP_FILE, strFileName);
					pThis->m_strBmpFileName = strFileName;

					break;
				}

				case IDC_RECT_MAP:
					{
						CCritSec::CLock lock (g_cs);
						pThis->m_rect = g_map.rectBound;
					}
					FillRect (_hWnd, pThis->m_rect);
					break;

				case IDC_RECT_VISIBLE:
					{
						CCritSec::CLock lock (g_cs);
						GetVisibleRect (pThis->m_rect);
					}
					FillRect (_hWnd, pThis->m_rect);
					break;

				case IDC_RECT_CUSTOM:
					if (EditRect (_hWnd, pThis->m_rect))
						FillRect (_hWnd, pThis->m_rect);
					break;

				case IDC_TILE:
					pThis->m_bIsTiled = ::IsDlgButtonChecked (_hWnd, IDC_TILE) == BST_CHECKED;
					::EnableWindow (::GetDlgItem (_hWnd, IDC_COLS), pThis->m_bIsTiled);
					::EnableWindow (::GetDlgItem (_hWnd, IDC_ROWS), pThis->m_bIsTiled);
					break;
			}
			break;

	    case WM_NOTIFY: {
            const NMHDR * const pInfo = reinterpret_cast<NMHDR *> (_lParam);
            switch (pInfo->code) {
				case PSN_SETACTIVE:
					PropSheet_SetWizButtons (::GetParent (_hWnd), PSWIZB_FINISH);
					break;

				case PSN_QUERYCANCEL:
					g_bCanceled = true;
					break;

				case PSN_WIZFINISH:
					if (DoesFileExist (pThis->GetBmpFileName ().c_str ())) {
						if (YesNoMsgBox (GetStr (IDS_FILE_REQUEST_OVERWITE), pThis->GetBmpFileName ().c_str ()) == false) {
							::SetWindowLong (_hWnd, DWL_MSGRESULT, TRUE);
							return TRUE;
						}
					}
					if (DoesFileExist (pThis->GetMapFileName ().c_str ())) {
						if (YesNoMsgBox (GetStr (IDS_FILE_REQUEST_OVERWITE), pThis->GetMapFileName ().c_str ()) == false) {
							::SetWindowLong (_hWnd, DWL_MSGRESULT, TRUE);
							return TRUE;
						}
					}
					if (
						! pThis->_GetField (_hWnd, IDC_COLS, "Invalid number of columns.", pThis->m_cCols) ||
						! pThis->_GetField (_hWnd, IDC_ROWS, "Invalid number of rows.",    pThis->m_cRows)
					) {
						::SetWindowLong (_hWnd, DWL_MSGRESULT, TRUE);
						return TRUE;
					}
					break;
            }
        }
        break;

		case WM_DESTROY:
			DeleteStaticPicture (_hWnd, IDC_BITMAP);
			break;
	}

	return FALSE;
}

bool COziMapWizard::_GetField (HWND _hWnd, UINT _uiId, const char * _strErrorMsg, size_t & _cValue) {
	BOOL bTranslated = FALSE;
    _cValue = ::GetDlgItemInt (_hWnd, _uiId, & bTranslated, FALSE);
    if (! bTranslated || _cValue == 0) {
        ErrorMsgBox (_strErrorMsg);
        return false;
    }
    return true;
}

LoadStatus_t COziMapWizard::Show (const char * _strFileName) {
	// Prepare title.
	string_t strTitle = "Export ";
	strTitle.append (_strFileName);

	// Prepare pages.
	const size_t c_cPages = 1;
	PROPSHEETPAGE pshp [c_cPages];
	::memset (pshp, 0, sizeof (pshp));
	for (size_t cPage = 0; cPage < c_cPages; ++ cPage) {
		pshp [cPage].dwSize    = sizeof (PROPSHEETPAGE);
		pshp [cPage].dwFlags   = PSP_DEFAULT | PSP_USETITLE;
		pshp [cPage].hInstance = g_hResInst;
		pshp [cPage].lParam    = reinterpret_cast<LPARAM> (this);
		pshp [cPage].pszTitle  = strTitle.c_str ();
	}

	pshp [0].pszTemplate = MAKEINTRESOURCE (IDD_EXPORT_MAP);
	pshp [0].pfnDlgProc  = _PageProc;

	// Prepare header.
	PROPSHEETHEADER psh;
	::memset (& psh, 0, sizeof (psh));
	psh.dwSize     = sizeof (psh);
	psh.dwFlags    = PSH_WIZARD | PSH_PROPTITLE | PSH_PROPSHEETPAGE;
	psh.hwndParent = g_hWnd;
	psh.hInstance  = g_hResInst;
	psh.nPages     = c_cPages;
	psh.nStartPage = 0;
	psh.ppsp       = pshp;

	g_bCanceled = false;

	// Show the wizard.
	if (::PropertySheet (& psh) <= 0)
		return g_bCanceled ? lsCanceled : lsFailed;

	return lsOK;
}
